package com.ty.cloudpicture.manager;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.ty.cloudpicture.model.dto.picture.PictureQueryRequest;
import com.ty.cloudpicture.model.entity.Picture;
import com.ty.cloudpicture.model.vo.PictureVO;
import com.ty.cloudpicture.service.PictureService;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
@AllArgsConstructor
public class PictureCacheManager {
    private static final String PICTURE_CACHE_KEY = "cp:listPageVO:%s";
    private static final int minExpireTime = 5;
    private static final int maxExpireTime = 60;
    private static final TimeUnit timeUnit = TimeUnit.MINUTES;

    private  final PictureService pictureService;

    private final Cache<String, String> LOCAL_CACHE =
            Caffeine.newBuilder().initialCapacity(1024)
                    .maximumSize(10000L)
                    // 缓存 5 分钟移除
                    .expireAfterWrite(RandomUtil.randomInt(minExpireTime, maxExpireTime), timeUnit)
                    .build();
    public Page<PictureVO> getPageVOCache(PictureQueryRequest pictureQueryRequest){
        String hashKey= JSONUtil.toJsonStr(pictureQueryRequest);
        String cacheKey = String.format(PICTURE_CACHE_KEY, hashKey);
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        Page<PictureVO> cacheValue = tryGetCacheValue(cacheKey, opsForValue);
        if (cacheValue != null){
            return cacheValue;
        }
        Page<Picture> picturePage = pictureService.page(new Page<>(pictureQueryRequest.getCurrent(), pictureQueryRequest.getPageSize()),
                pictureService.getQueryWrapper(pictureQueryRequest));
        LOCAL_CACHE.put(cacheKey, JSONUtil.toJsonStr(pictureService.getPictureVOPage(picturePage)));
        opsForValue.set(cacheKey, JSONUtil.toJsonStr(pictureService.getPictureVOPage(picturePage)),
                RandomUtil.randomInt(minExpireTime, maxExpireTime), timeUnit);
        return pictureService.getPictureVOPage(picturePage);
    }
        private Page<PictureVO> tryGetCacheValue(String key,ValueOperations<String, String> ops){
            String cacheIfPresent = LOCAL_CACHE.getIfPresent(key);
            if (cacheIfPresent != null){
                return JSONUtil.toBean(cacheIfPresent, Page.class);
            }
            String cacheValue = ops.get(key);
            if (cacheValue != null){
                Page<PictureVO> pageValue = JSONUtil.toBean(cacheValue, Page.class);
                LOCAL_CACHE.put(key, cacheValue);
                return pageValue;
            }
            return null;
        }
}
